import { IResponse } from "../types/CommonType";
import fs from "fs";
import path from "path";
import xlsx from "xlsx";
/**
 * 格式化响应体
 */
export function formatResponse<T>(data: T, msg: string = "", code: number = 200): IResponse<T> {
  return {
    code,
    msg,
    data,
  };
}

export function pick<T extends {}, K extends keyof T>(obj: T, keys: readonly K[]): Pick<T, K> {
  const result: any = {};
  keys.forEach((key) => {
    if (key in obj) {
      result[key] = obj[key];
    }
  });
  return result as Pick<T, K>;
}

/**
 * 格式化分页查询查询数据
 */
export function formatRequestQuery(params: any, props: string[] = []) {
  const result = {
    query: {
      current: +params.current || 1,
      size: +params.size || 10,
    },
    other: pick(params, props),
  };
  return result;
}

/**
 * 构建属性结构
 */
interface IHasIdAndParentId {
  id?: number;
  parentId?: number | null;
  children?: any[];
}

/**
 * 将数组格式化成父子结构
 * @param list 目标数组
 * @param key 主键id
 * @param parentKey 父级id名称
 * @returns
 */
export function getTreeStructure<T extends IHasIdAndParentId>(
  list: T[],
  key: string = "id",
  parentKey: string = "parentId"
) {
  function buildTree(parentId: number): T[] {
    return list
      .filter((item) => item[parentKey] === parentId)
      .map((child) => {
        const nextTree = buildTree(child[key]);
        if (nextTree.length > 0) {
          child.children = nextTree;
        }
        return child;
      });
  }

  // 找最外层节点
  const roots = list.filter((item) => !item[parentKey]);
  // 根据最外层一次找子集
  roots.forEach((item) => {
    item.children = buildTree(item[key]);
  });
  return roots;
}

export function formatDate(date: Date | string, format: string = "YYYY-MM-DD HH:mm:ss"): string {
  const parsedDate = date instanceof Date ? date : new Date(date);

  const formats: { [key: string]: () => string } = {
    YYYY: () => parsedDate.getFullYear().toString(),
    MM: () => String(parsedDate.getMonth() + 1).padStart(2, "0"),
    DD: () => String(parsedDate.getDate()).padStart(2, "0"),
    HH: () => String(parsedDate.getHours()).padStart(2, "0"),
    mm: () => String(parsedDate.getMinutes()).padStart(2, "0"),
    ss: () => String(parsedDate.getSeconds()).padStart(2, "0"),
  };

  // 使用正则表达式匹配并替换格式字符串中的模式
  return format.replace(/YYYY|MM|DD|HH|mm|ss/g, (matched) => {
    return formats[matched] ? formats[matched]() : matched; // 如果存在对应的格式处理函数，则调用它
  });
}

export async function checkDirExists(path) {
  try {
    await fs.promises.stat(path);
 
    return true;
  } catch (err) {
    if (err.code === "ENOENT") {
      return false;
    } else {
      throw err;
    }
  }
}

export async function createDirectory(path: string) {
  return fs.promises.mkdir(path, { recursive: true });
}

export async function writeToFile(filename: string, text: string) {
  return fs.promises.writeFile(filename, text);
}

export async function appendFile(filePath: string, text: string) {
  return fs.promises.appendFile(filePath, text);
}

export function getRandom(min: number, max: number): number {
  if (min > max) {
    throw new Error("Minimum value must be less than or equal to maximum value.");
  }
  return Math.floor(Math.random() * (max - min + 1)) + min;
}

/**
 * 获取随机头像
 */
export async function getAvatar() {
  const dir = path.resolve(__dirname, "../../public/static/avatar");
  const files = await fs.promises.readdir(dir);
  return "/static/avatar/" + files[getRandom(0, files.length - 1)];
}

export function parseTime(time, pattern?: any) {
  if (arguments.length === 0 || !time) {
    return null;
  }
  const format = pattern || "{y}-{m}-{d} {h}:{i}:{s}";
  let date;
  if (typeof time === "object") {
    date = time;
  } else {
    if (typeof time === "string" && /^[0-9]+$/.test(time)) {
      time = parseInt(time);
    } else if (typeof time === "string") {
      time = time
        .replace(new RegExp(/-/gm), "/")
        .replace("T", " ")
        .replace(new RegExp(/\.[\d]{3}/gm), "");
    }
    if (typeof time === "number" && time.toString().length === 10) {
      time = time * 1000;
    }
    date = new Date(time);
  }
  const formatObj: any = {
    y: date.getFullYear(),
    m: date.getMonth() + 1,
    d: date.getDate(),
    h: date.getHours(),
    i: date.getMinutes(),
    s: date.getSeconds(),
    a: date.getDay(),
  };
  const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
    let value = formatObj[key];
    // Note: getDay() returns 0 on Sunday
    if (key === "a") {
      return ["日", "一", "二", "三", "四", "五", "六"][value];
    }
    if (result.length > 0 && value < 10) {
      value = "0" + value;
    }
    return value || 0;
  });
  return time_str;
}

/**
 * 解析excel
 */
export function readExcel(filePath: string) {
  const fileContent = xlsx.readFile(filePath); // 读取excel文件
  const name = fileContent.SheetNames[0]; // 获取excel第一张sheet的名字
  const sheet = fileContent.Sheets[name]; // 获取excel第一张sheet中的数据
  const jsonData: any = xlsx.utils.sheet_to_json(sheet); // 将数据转成 json 格式

  // 转换日期格式
  jsonData.forEach((row) => {
    Object.keys(row).forEach((key) => {
      if (typeof row[key] === "number") {
        row[key] = convertDate(row[key]);
      }
    });
  });

  return jsonData;
}

function convertDate(num: number) {
  const date = new Date(1899, 11, 30); // Excel的起始日期
  date.setDate(date.getDate() + num);
  return `${parseTime(date)}`;
}

export async function removeFile(path: string) {
  return fs.promises.unlink(path);
}

export function getRandomStr() {
  return Date.now().toString(32) + Math.random().toString(32).slice(2, 8);
}

export function deepClone(target: any) {
  // target 为空或者不是对象
  if (!target || typeof target !== "object") {
    return target;
  }
  if (target.constructor === Date || target.constructor === RegExp) {
    return target;
  }

  var result;
  if (Array.isArray(target)) {
    result = [];
    for (var i in target) {
      result.push(deepClone(target[i]));
    }
  } else {
    result = {};
    for (var i in target) {
      result[i] = deepClone(target[i]);
    }
  }
  return result;
}
